﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace NeurOthello.Logic
{

    public delegate void UpdateEventHandler(object sender, EventArgs e);

    public abstract class Othello
    {
        public event UpdateEventHandler Update;

        public static int boardSize = 8;
        protected const int PLAYER1 = 1, PLAYER2 = 2, nSquares = 64;  

        private static int DIRECTIONS = 8;
        public static double NullToken = -999999;

        public abstract int[,] Gameboard { get; }
        public abstract double[] Inputboard { get; }

        public Position LastMove { get { return lastMove; } } 
        protected Position lastMove; 
       
        private Player player1, player2;
        public bool CurrentIsAi
        {
            get
            {
                if (PlayerTurn == 1)
                    return player1.Set.IsCpu;
                else if (PlayerTurn == 2)
                    return player2.Set.IsCpu;
                else return false;
            }
        }
        public int PlayerTurn { get; set; }
        public int Opponent { get { return 3 - PlayerTurn; } }

        public Othello()
        {

        }

        protected virtual void OnUpdate(EventArgs e)
        {
            if (Update != null)
                Update(this, e);
        }

        public int playGame(Player player1, Player player2)
        {
            ResetBoard();
            PlayerTurn = 1;
            this.player1 = player1;
            this.player2 = player2;
          
            while (PlayerTurn != 0)
            {
                switch (PlayerTurn)
                {
                    case (PLAYER1):                        
                            PlaceMarker(PLAYER1, player1.MakeMove(PLAYER1));
                        break;
                    case (PLAYER2):
                            PlaceMarker(PLAYER2, player2.MakeMove(PLAYER2));
                        break;
                }                
            }
            int b = 0, w= 0, u = 0;
            boardCount(ref b, ref w, ref u);
    
            if (b > w)
            {                
                return 1; 
            }
            if (b < w)
            {
                return 2;
            }
            else
            {
                return 0;
            }
        }

        public int playTrainingGame(Player player1, Player player2)
        {
            ResetBoard();
            PlayerTurn = 1;
            while (PlayerTurn != 0)
            {
                switch (PlayerTurn)
                {
                    case (PLAYER1):
                        PlaceMarker(PLAYER1, player1.MakeTrainingMove(PLAYER1));
                        break;
                    case (PLAYER2):
                        PlaceMarker(PLAYER2, player2.MakeTrainingMove(PLAYER2));
                        break;
                }
            }
            int b = 0, w = 0, u = 0;
            boardCount(ref b, ref w, ref u);

            if (b > w)
            {
                player1.TrainPlayer(new double[2] { 1, 0 });
                player2.TrainPlayer(new double[2] { 1, 0 });
                return 1;
            }
            else if (b < w)
            {
                player1.TrainPlayer(new double[2] { 0, 1 });
                player2.TrainPlayer(new double[2] { 0, 1 });
                return 2;
            }
            else
            {
                player1.TrainPlayer(new double[2] { 0.5, 0.5 });
                player2.TrainPlayer(new double[2] { 0.5, 0.5 });
                return 0;
            }
            
        }

        public abstract void ResetBoard();

        public abstract void SetSquare(int x, int y, int playerId);

        public virtual bool PlaceMarker(int playerId, int x, int y)
        {
            lastMove = new Position(x, y);
            OnUpdate(EventArgs.Empty);            
            return true;
        }

        public abstract bool PlaceMarker(int playerId, Position pos);

        public abstract bool HasMove(int playerId);

        public abstract int CountMoves(int playerId);

        public abstract void ClearTranspositions();

        public abstract void AddTranspositionValue(double val);

        public abstract double FindTranspositionValue();

        public abstract Position[] AllMoves(int playerId);

        public abstract void boardCount(ref int black, ref int white, ref int unMarked);

        public abstract int SafeScore(int playerId);
    }
}
